#include "arabic_reshaper.h"
#include <stdbool.h>
//#include <wchar.h>
#include <string.h>

#define MAX_UNICODE_LEN (128)
//#define X86_TEST
#ifdef X86_TEST
#include <assert.h>
#define Expects(cond) assert(cond)
#define Ensures(cond) assert(cond)
#define PLATFORM_WEAK
#else
#include <platform_assert.h>
#include <platform_toolchain.h>
#include "utf8_to_unicode.h"
#endif

PLATFORM_WEAK size_t wcslen(uint16_t const *s)
{
    size_t len = 0;
    while (s[len] != L'\0')
    {
        if (s[++len] == L'\0')
            return len;
        if (s[++len] == L'\0')
            return len;
        if (s[++len] == L'\0')
            return len;
        ++len;
    }
    return len;
}
#ifdef X86_TEST
static int get_utf8_size(uint8_t utf_head)
{
    int num = 0, i = 0;

    // printf("input:%02x\n", input);
    for (i = 0; i < 8; i++)
    {
        if (((utf_head >> (7 - i)) & 0x01))
        {
            num++;
        }
        else
        {
            break;
        }
    }

    return (num > 0) ? num : 0;
}
//返回UTF8字符占用字节数,返回0表示失败
uint8_t utf_to_unicode(uint8_t const utf_buf[], uint16_t *p_unicode)
{
    // b1 表示UTF-8编码的buf中的高字节, b2 表示次高字节, ...
    char b1, b2, b3, b4, b5, b6;

    *p_unicode = 0x0;
    int utf_bytes = get_utf8_size(utf_buf[0]);

    if (utf_buf[0] == 0)
    {
        return 0;
    }

    uint8_t *p_out = (uint8_t *)p_unicode;

    switch (utf_bytes)
    {
    case 0:
        *p_out = *utf_buf;
        utf_bytes += 1;
        break;
    case 2:
        b1 = *utf_buf;
        b2 = *(utf_buf + 1);
        if ((b2 & 0xC0) != 0x80)
        {
            return 0;
        }
        *p_out = (b1 << 6) + (b2 & 0x3F);
        *(p_out + 1) = (b1 >> 2) & 0x07;
        break;
    case 3:
        b1 = *utf_buf;
        b2 = *(utf_buf + 1);
        b3 = *(utf_buf + 2);
        if (((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80))
            return 0;
        *p_out = (b2 << 6) + (b3 & 0x3F);
        *(p_out + 1) = (b1 << 4) + ((b2 >> 2) & 0x0F);
        break;
    case 4:
        b1 = *utf_buf;
        b2 = *(utf_buf + 1);
        b3 = *(utf_buf + 2);
        b4 = *(utf_buf + 3);
        if (((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80) || ((b4 & 0xC0) != 0x80))
            return 0;
        *p_out = (b3 << 6) + (b4 & 0x3F);
        *(p_out + 1) = (b2 << 4) + ((b3 >> 2) & 0x0F);
        *(p_out + 2) = ((b1 << 2) & 0x1C) + ((b2 >> 4) & 0x03);
        break;
    case 5:
        b1 = *utf_buf;
        b2 = *(utf_buf + 1);
        b3 = *(utf_buf + 2);
        b4 = *(utf_buf + 3);
        b5 = *(utf_buf + 4);
        if (((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80) || ((b4 & 0xC0) != 0x80) || ((b5 & 0xC0) != 0x80))
            return 0;
        *p_out = (b4 << 6) + (b5 & 0x3F);
        *(p_out + 1) = (b3 << 4) + ((b4 >> 2) & 0x0F);
        *(p_out + 2) = (b2 << 2) + ((b3 >> 4) & 0x03);
        *(p_out + 3) = (b1 << 6);
        break;
    case 6:
        b1 = *utf_buf;
        b2 = *(utf_buf + 1);
        b3 = *(utf_buf + 2);
        b4 = *(utf_buf + 3);
        b5 = *(utf_buf + 4);
        b6 = *(utf_buf + 5);
        if (((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80) || ((b4 & 0xC0) != 0x80) || ((b5 & 0xC0) != 0x80) || ((b6 & 0xC0) != 0x80))
            return 0;
        *p_out = (b5 << 6) + (b6 & 0x3F);
        *(p_out + 1) = (b5 << 4) + ((b6 >> 2) & 0x0F);
        *(p_out + 2) = (b3 << 2) + ((b4 >> 4) & 0x03);
        *(p_out + 3) = ((b1 << 6) & 0x40) + (b2 & 0x3F);
        break;
    default:
        return 0;
    }
    return utf_bytes;
}

#endif

typedef enum __code_form_t
{
    code_form_isolated,
    code_form_inital,
    code_form_medial,
    code_form_final,
    code_form_count,
    code_form_prototype,
} code_form_t;

typedef struct __reshaper_info_t
{
    uint16_t code;
    uint16_t reshaper[code_form_count];
} reshaper_info_t;

static reshaper_info_t const reshaper_table[] = {
    {0x0621, 0xfe80, 0x0000, 0x0000, 0x0000}, {0x0622, 0xfe81, 0x0000, 0x0000, 0xfe82}, {0x0623, 0xfe83, 0x0000, 0x0000, 0xfe84}, {0x0624, 0xfe85, 0x0000, 0x0000, 0xfe86},
    {0x0625, 0xfe87, 0x0000, 0x0000, 0xfe88}, {0x0626, 0xfe89, 0xfe8b, 0xfe8c, 0xfe8a}, {0x0627, 0xfe8d, 0x0000, 0x0000, 0xfe8e}, {0x0628, 0xfe8f, 0xfe91, 0xfe92, 0xfe90},
    {0x0629, 0xfe93, 0x0000, 0x0000, 0xfe94}, {0x062a, 0xfe95, 0xfe97, 0xfe98, 0xfe96}, {0x062b, 0xfe99, 0xfe9b, 0xfe9c, 0xfe9a}, {0x062c, 0xfe9d, 0xfe9f, 0xfea0, 0xfe9e},
    {0x062d, 0xfea1, 0xfea3, 0xfea4, 0xfea2}, {0x062e, 0xfea5, 0xfea7, 0xfea8, 0xfea6}, {0x062f, 0xfea9, 0x0000, 0x0000, 0xfeaa}, {0x0630, 0xfeab, 0x0000, 0x0000, 0xfeac},
    {0x0631, 0xfead, 0x0000, 0x0000, 0xfeae}, {0x0632, 0xfeaf, 0x0000, 0x0000, 0xfeb0}, {0x0633, 0xfeb1, 0xfeb3, 0xfeb4, 0xfeb2}, {0x0634, 0xfeb5, 0xfeb7, 0xfeb8, 0xfeb6},
    {0x0635, 0xfeb9, 0xfebb, 0xfebc, 0xfeba}, {0x0636, 0xfebd, 0xfebf, 0xfec0, 0xfebe}, {0x0637, 0xfec1, 0xfec3, 0xfec4, 0xfec2}, {0x0638, 0xfec5, 0xfec7, 0xfec8, 0xfec6},
    {0x0639, 0xfec9, 0xfecb, 0xfecc, 0xfeca}, {0x063a, 0xfecd, 0xfecf, 0xfed0, 0xfece}, {0x0640, 0x0640, 0x0640, 0x0640, 0x0640}, {0x0641, 0xfed1, 0xfed3, 0xfed4, 0xfed2},
    {0x0642, 0xfed5, 0xfed7, 0xfed8, 0xfed6}, {0x0643, 0xfed9, 0xfedb, 0xfedc, 0xfeda}, {0x0644, 0xfedd, 0xfedf, 0xfee0, 0xfede}, {0x0645, 0xfee1, 0xfee3, 0xfee4, 0xfee2},
    {0x0646, 0xfee5, 0xfee7, 0xfee8, 0xfee6}, {0x0647, 0xfee9, 0xfeeb, 0xfeec, 0xfeea}, {0x0648, 0xfeed, 0x0000, 0x0000, 0xfeee}, {0x0649, 0xfeef, 0xfbe8, 0xfbe9, 0xfef0},
    {0x064a, 0xfef1, 0xfef3, 0xfef4, 0xfef2}, {0x0671, 0xfb50, 0x0000, 0x0000, 0xfb51}, {0x0677, 0xfbdd, 0x0000, 0x0000, 0x0000}, {0x0679, 0xfb66, 0xfb68, 0xfb69, 0xfb67},
    {0x067a, 0xfb5e, 0xfb60, 0xfb61, 0xfb5f}, {0x067b, 0xfb52, 0xfb54, 0xfb55, 0xfb53}, {0x067e, 0xfb56, 0xfb58, 0xfb59, 0xfb57}, {0x067f, 0xfb62, 0xfb64, 0xfb65, 0xfb63},
    {0x0680, 0xfb5a, 0xfb5c, 0xfb5d, 0xfb5b}, {0x0683, 0xfb76, 0xfb78, 0xfb79, 0xfb77}, {0x0684, 0xfb72, 0xfb74, 0xfb75, 0xfb73}, {0x0686, 0xfb7a, 0xfb7c, 0xfb7d, 0xfb7b},
    {0x0687, 0xfb7e, 0xfb80, 0xfb81, 0xfb7f}, {0x0688, 0xfb88, 0x0000, 0x0000, 0xfb89}, {0x068c, 0xfb84, 0x0000, 0x0000, 0xfb85}, {0x068d, 0xfb82, 0x0000, 0x0000, 0xfb83},
    {0x068e, 0xfb86, 0x0000, 0x0000, 0xfb87}, {0x0691, 0xfb8c, 0x0000, 0x0000, 0xfb8d}, {0x0698, 0xfb8a, 0x0000, 0x0000, 0xfb8b}, {0x06a4, 0xfb6a, 0xfb6c, 0xfb6d, 0xfb6b},
    {0x06a6, 0xfb6e, 0xfb70, 0xfb71, 0xfb6f}, {0x06a9, 0xfb8e, 0xfb90, 0xfb91, 0xfb8f}, {0x06ad, 0xfbd3, 0xfbd5, 0xfbd6, 0xfbd4}, {0x06af, 0xfb92, 0xfb94, 0xfb95, 0xfb93},
    {0x06b1, 0xfb9a, 0xfb9c, 0xfb9d, 0xfb9b}, {0x06b3, 0xfb96, 0xfb98, 0xfb99, 0xfb97}, {0x06ba, 0xfb9e, 0x0000, 0x0000, 0xfb9f}, {0x06bb, 0xfba0, 0xfba2, 0xfba3, 0xfba1},
    {0x06be, 0xfbaa, 0xfbac, 0xfbad, 0xfbab}, {0x06c0, 0xfba4, 0x0000, 0x0000, 0xfba5}, {0x06c1, 0xfba6, 0xfba8, 0xfba9, 0xfba7}, {0x06c5, 0xfbe0, 0x0000, 0x0000, 0xfbe1},
    {0x06c6, 0xfbd9, 0x0000, 0x0000, 0xfbda}, {0x06c7, 0xfbd7, 0x0000, 0x0000, 0xfbd8}, {0x06c8, 0xfbdb, 0x0000, 0x0000, 0xfbdc}, {0x06c9, 0xfbe2, 0x0000, 0x0000, 0xfbe3},
    {0x06cb, 0xfbde, 0x0000, 0x0000, 0xfbdf}, {0x06cc, 0xfbfc, 0xfbfe, 0xfbff, 0xfbfd}, {0x06d0, 0xfbe4, 0xfbe6, 0xfbe7, 0xfbe5}, {0x06d2, 0xfbae, 0x0000, 0x0000, 0xfbaf},
    {0x06d3, 0xfbb0, 0x0000, 0x0000, 0xfbb1}, {0x200d, 0x200d, 0x200d, 0x200d, 0x200d},
};

typedef struct __harakat_info_t
{
    uint16_t start;
    uint16_t end;
} harakat_info_t;

static harakat_info_t const harakat_table[] = {{0x0610, 0x061a}, {0x064b, 0x065f}, {0x0670, 0x0670}, {0x06d6, 0x06dc}, {0x06df, 0x06e8},
                                               {0x06ea, 0x06ed}, {0x08d4, 0x08e1}, {0x08d4, 0x08ed}, {0x08e3, 0x08ff}};
static uint16_t const arabic_ligature_allah[] = {0x627, 0x644, 0x644, 0x647};
static uint16_t const arabic_ligature_lam_with_alef[] = {0x644, 0x627};
static uint16_t const arabic_ligature_lam_with_alef_with_hamza_above[] = {0x644, 0x623};
static uint16_t const arabic_ligature_lam_with_alef_with_hamza_below[] = {0x644, 0x625};
static uint16_t const arabic_ligature_lam_with_alef_with_madda_above[] = {0x644, 0x622};
typedef struct __ligatures_info_t
{
    uint16_t const *format;
    int format_len;
    uint16_t reshaper[code_form_count];
} ligatures_info_t;
static ligatures_info_t const ligatures_table[] = {
    {arabic_ligature_allah, sizeof(arabic_ligature_allah), 0xfdf2, 0x0000, 0x0000, 0x0000},
    {arabic_ligature_lam_with_alef, sizeof(arabic_ligature_lam_with_alef), 0xfefb, 0x0000, 0x0000, 0xfefc},
    {arabic_ligature_lam_with_alef_with_hamza_above, sizeof(arabic_ligature_lam_with_alef_with_hamza_above), 0xfef7, 0x0000, 0x0000, 0xfef8},
    {arabic_ligature_lam_with_alef_with_hamza_below, sizeof(arabic_ligature_lam_with_alef_with_hamza_below), 0xfef9, 0x0000, 0x0000, 0xfefa},
    {arabic_ligature_lam_with_alef_with_madda_above, sizeof(arabic_ligature_lam_with_alef_with_madda_above), 0xfef5, 0x0000, 0x0000, 0xfef6},
};

typedef struct __align_type_info_t
{
    uint16_t start;
    uint8_t count;
    align_type_t type;
} align_type_info_t;
align_type_info_t const align_type_code_array[44] = {
    {0x0000, 1, align_type_unknown}, {0x000d, 1, align_type_unknown},  {0x0020, 2, align_type_unknown},  {0x002c, 3, align_type_unknown},  {0x0030, 11, align_type_unknown},
    {0x00a0, 1, align_type_unknown}, {0x00ab, 1, align_type_unknown},  {0x00bb, 1, align_type_unknown},  {0x034f, 1, align_type_unknown},  {0x0600, 4, align_type_left},
    {0x0604, 8, align_type_unknown}, {0x060c, 10, align_type_left},    {0x0616, 5, align_type_unknown},  {0x061b, 1, align_type_left},     {0x061c, 1, align_type_unknown},
    {0x061e, 2, align_type_left},    {0x0620, 1, align_type_unknown},  {0x0621, 26, align_type_left},    {0x063b, 5, align_type_unknown},  {0x0640, 31, align_type_left},
    {0x065f, 1, align_type_unknown}, {0x0660, 160, align_type_left},   {0x0750, 30, align_type_left},    {0x076e, 18, align_type_unknown}, {0x08a0, 21, align_type_unknown},
    {0x08b6, 8, align_type_unknown}, {0x08d4, 44, align_type_unknown}, {0x200b, 7, align_type_unknown},  {0x204f, 1, align_type_unknown},  {0x25cc, 1, align_type_unknown},
    {0x2e41, 1, align_type_unknown}, {0xfb50, 98, align_type_left},    {0xfbb2, 16, align_type_unknown}, {0xfbd3, 255, align_type_left},   {0xfcd2, 108, align_type_left},
    {0xfd3e, 2, align_type_unknown}, {0xfd50, 64, align_type_left},    {0xfd92, 54, align_type_left},    {0xfdf0, 12, align_type_left},    {0xfdfc, 1, align_type_unknown},
    {0xfdfd, 1, align_type_left},    {0xfe70, 5, align_type_left},     {0xfe76, 135, align_type_left},   {0xffff, 1, align_type_unknown},
};

/**
 * @brief
 *
 * @param code
 * @return uint16_t
 */
static align_type_t get_align_type(uint16_t code)
{
    for (int i = 0; i < sizeof(align_type_code_array) / sizeof(align_type_code_array[0]); i++)
    {
        if (align_type_code_array[i].start <= code && code < align_type_code_array[i].start + align_type_code_array[i].count)
        {
            return align_type_code_array[i].type;
        }
    }
    return align_type_right;
}
/**
 * @brief 返回当前是否为阿拉伯字母
 *
 * @param code
 * @return true
 * @return false
 */
static reshaper_info_t const *get_reshaper_info(uint16_t code)
{
    for (int i = 0; i < sizeof(reshaper_table) / sizeof(reshaper_table[0]); i++)
    {
        if (reshaper_table[i].code == code)
        {
            return &reshaper_table[i];
        }
    }
    return 0;
}

///**
// * @brief 是否能作为尾变形或者中间变形
// *
// * @param code
// * @return true
// * @return false
// */
// static bool check_join_to_last(uint16_t code)
//{
//    reshaper_info_t const *pinfo = get_reshaper_info(code);
//    if (!pinfo)
//    {
//        return false;
//    }
//    if (pinfo->reshaper[code_form_medial] == 0 && pinfo->reshaper[code_form_final] == 0)
//    {
//        return false;
//    }
//    return true;
//}

static int delete_harakat(uint16_t *unicode_str, int unicode_str_len)
{
    // int ret_len = 0;
    int del_count = 0;
    bool is_skip = false;
    for (int i = 0; i < unicode_str_len; i++)
    {
        is_skip = false;
        for (int j = 0; j < sizeof(harakat_table) / sizeof(harakat_table[0]); j++)
        {
            if (harakat_table[j].start <= unicode_str[i] && harakat_table[j].end >= unicode_str[i])
            {
                del_count++;
                is_skip = true;
            }
        }
        if (!is_skip && del_count != 0)
        {
            unicode_str[i - del_count] = unicode_str[i];
        }
    }
    unicode_str[unicode_str_len - del_count] = 0;
    return unicode_str_len - del_count;
}
static void reshaper_without_ligatures(uint16_t const *unicode_str, int unicode_str_len, code_form_t *form)
{
    reshaper_info_t const *p_code_info = 0;
    reshaper_info_t const *p_last_code_info = 0;
    for (int index = 0; index < unicode_str_len; ++index)
    {
        p_code_info = get_reshaper_info(unicode_str[index]);
        if (p_code_info == 0)
        {
            form[index] = code_form_prototype;
        }
        else if (index == 0 || unicode_str[index - 1] == '\x0a')
        {
            form[index] = code_form_isolated;
        }
        else
        {
            p_last_code_info = get_reshaper_info(unicode_str[index - 1]);
            if (form[index - 1] == code_form_prototype)
            {
                form[index] = code_form_isolated;
            }
            else if (p_code_info->reshaper[code_form_medial] == 0 && p_code_info->reshaper[code_form_final] == 0)
            {
                form[index] = code_form_isolated;
            }
            else if (p_last_code_info->reshaper[code_form_inital] == 0 && p_last_code_info->reshaper[code_form_medial] == 0)
            {
                form[index] = code_form_isolated;
            }
            else if (form[index - 1] == code_form_final && p_last_code_info->reshaper[code_form_medial] == 0)
            {
                form[index] = code_form_isolated;
            }
            else if (form[index - 1] == code_form_isolated)
            {
                form[index - 1] = code_form_inital;
                form[index] = code_form_final;
            }
            else
            {
                form[index - 1] = code_form_medial;
                form[index] = code_form_final;
            }
        }
    }
}

/**
 * @brief 如果当前符合连写规则，就把规则返回
 *
 * @param unicode_str
 * @param unicode_str_len
 * @param index
 * @return ligatures_info_t const*
 */
ligatures_info_t const *get_ligatures_reshaper_info(uint16_t *unicode_str, int unicode_str_len, int index)
{
    for (int i = 0; i < sizeof(ligatures_table) / sizeof(ligatures_table[0]); i++)
    {
        if (unicode_str_len - index >= ligatures_table[i].format_len)
        {
            if (memcmp(ligatures_table[i].format, (const uint8_t *)&unicode_str[index], ligatures_table[i].format_len) == 0)
            {
                return &ligatures_table[i];
            }
        }
    }
    return 0;
}

static bool reshaper(uint16_t *unicode_str)
{
    // Expects(unicode_str);
    if (unicode_str == 0)
    {
        return false;
    }
    int unicode_str_len = wcslen(unicode_str);
    // Expects(unicode_str_len < MAX_UNICODE_LEN && unicode_str_len > 0);
    if (unicode_str_len >= MAX_UNICODE_LEN || unicode_str_len <= 0)
    {
        return false;
    }
    unicode_str_len = delete_harakat(unicode_str, unicode_str_len);
    code_form_t form[MAX_UNICODE_LEN] = {(code_form_t)0};
    reshaper_without_ligatures(unicode_str, unicode_str_len, form);
    int write_index = 0;
    uint16_t write_code = 0;
    reshaper_info_t const *p_code_info = 0;
    code_form_t head_format = (code_form_t)0;
    code_form_t tail_format = (code_form_t)0;
    ligatures_info_t const *reshaper_info = 0;
    for (int index = 0; index < unicode_str_len; ++index)
    {
        write_code = unicode_str[index];
        reshaper_info = get_ligatures_reshaper_info(unicode_str, unicode_str_len, index);
        if (reshaper_info == 0)
        {
            switch (form[index])
            {
            case code_form_isolated:
            case code_form_inital:
            case code_form_medial:
            case code_form_final:
                p_code_info = get_reshaper_info(unicode_str[index]);
                Ensures(p_code_info);
                if (p_code_info == 0)
                {
                    goto WRITE;
                }
                Ensures(p_code_info->reshaper[form[index]]);
                if (p_code_info->reshaper[form[index]] == 0)
                {
                    goto WRITE;
                }
                write_code = p_code_info->reshaper[form[index]];
                goto WRITE;
            case code_form_prototype:
                goto WRITE;
            default:
                Ensures(0);
                goto WRITE;
            }
        }
        else
        {
            head_format = form[index];
            tail_format = form[index + reshaper_info->format_len / 2 - 1];
            switch (head_format)
            {
            case code_form_isolated:
            case code_form_inital:
            {
                switch (tail_format)
                {
                case code_form_isolated:
                case code_form_inital:
                case code_form_medial:
                case code_form_final:
                    Ensures(reshaper_info->reshaper[code_form_isolated]);
                    if (reshaper_info->reshaper[code_form_isolated] != 0)
                    {
                        write_code = reshaper_info->reshaper[code_form_isolated];
                    }
                    break;
                default:
                    Ensures(reshaper_info->reshaper[code_form_inital]);
                    if (reshaper_info->reshaper[code_form_inital] != 0)
                    {
                        write_code = reshaper_info->reshaper[code_form_inital];
                    }
                    break;
                }
            }
            break;
            default:
            {
                switch (tail_format)
                {
                case code_form_isolated:
                case code_form_inital:
                case code_form_medial:
                case code_form_final:
                    Ensures(reshaper_info->reshaper[code_form_final]);
                    if (reshaper_info->reshaper[code_form_final] != 0)
                    {
                        write_code = reshaper_info->reshaper[code_form_final];
                    }
                    break;
                default:
                    Ensures(reshaper_info->reshaper[code_form_medial]);
                    if (reshaper_info->reshaper[code_form_medial] != 0)
                    {
                        write_code = reshaper_info->reshaper[code_form_medial];
                    }
                    break;
                }
            } //!< default:

            } //!< switch (head_format)
            index = index + reshaper_info->format_len / 2 - 1;
            //!< 连写规则
        }
    WRITE:
        unicode_str[write_index] = write_code;
        ++write_index;
    }
    if (write_index < unicode_str_len)
    {
        unicode_str[write_index] = 0;
    }
    return true;
}

/**
 * @brief 递归处理，直到unicode_str_end，如果当前block与外部align不一致，那么就反转
 *
 * @param unicode_str_start
 * @param unicode_str_end
 * @param extern_block_align_type
 * @return uint16_t*
 */
static uint16_t *arabic_block_start(uint16_t *unicode_str_start, uint16_t *unicode_str_end, align_type_t extern_block_align_type)
{
    uint16_t *unicode_str = unicode_str_start;
    align_type_t type = align_type_invalid;
    align_type_t block_align_type = align_type_invalid;
    while (unicode_str < unicode_str_end)
    {
        if (*unicode_str == '\x0A')
        {
            break;
        }
        type = get_align_type(*unicode_str);
        if (block_align_type == align_type_invalid)
        {
            block_align_type = type;
        }
        else
        {
            if (type != block_align_type)
            {
                if (type == align_type_unknown && block_align_type == align_type_left)
                {
                    //!< 阿拉伯字母里夹着数字的情况
                    unicode_str = arabic_block_start(unicode_str, unicode_str_end, block_align_type);
                    continue;
                }
                else if ((type == align_type_left && block_align_type != align_type_left) || (type != align_type_left && block_align_type == align_type_left))
                {
                    break;
                }
            }
        }
        unicode_str++;
    }
    if (block_align_type != align_type_invalid &&
        ((extern_block_align_type == align_type_left && block_align_type != align_type_left) || (extern_block_align_type != align_type_left && block_align_type == align_type_left)))
    {
        uint16_t temp = 0;
        int i_end = (unicode_str - unicode_str_start) / 2;
        for (int i = 0; i < i_end; i++)
        {
            temp = unicode_str_start[i];
            unicode_str_start[i] = unicode_str_start[unicode_str - unicode_str_start - i - 1];
            unicode_str_start[unicode_str - unicode_str_start - i - 1] = temp;
        }
    }
    return unicode_str;
}
/**
 * @brief 返回变形后的text对齐类型
 *
 * @param unicode_str
 * @return align_type_t
 */
align_type_t arabic_reshaper(uint16_t *unicode_str)
{
    bool const result = reshaper(unicode_str);
    if (!result)
    {
        return align_type_right;
    }
    align_type_t first_align_type = align_type_invalid; //!< 返回值，第一段string的对齐类型
    // align_type_t string_align_type = align_type_invalid; //!< 当前段，string的对齐类型
    align_type_t block_align_type = align_type_invalid; //!< 当前快string的对齐类型
    // align_type_t type = align_type_invalid;              //!< 当前code 对齐类型
    int string_len = wcslen(unicode_str);
    uint16_t *const unicode_str_end = unicode_str + string_len;
    uint16_t *p_unicode_str = unicode_str;
    while (p_unicode_str < unicode_str_end)
    {
        if (block_align_type == align_type_invalid)
        {
            block_align_type = get_string_align_type(p_unicode_str);
            if (first_align_type == align_type_invalid)
            {
                first_align_type = block_align_type;
            }
        }
        p_unicode_str = arabic_block_start(p_unicode_str, unicode_str_end, block_align_type);
        while (*p_unicode_str == '\x0A')
        {
            p_unicode_str++;
            block_align_type = align_type_invalid;
        }
    }
    return first_align_type;
}

/**
 * @brief 判断当前句子是否为阿拉伯数字
 *
 * @param unicode_str
 */
align_type_t get_string_align_type(uint16_t const *unicode_str)
{
    int str_len = wcslen(unicode_str);
    align_type_t type = align_type_unknown;
    // 寻找第一个或align_type_right，如果直到句尾或换行都没有找到，那么就按align_type_right
    for (int i = 0; i < str_len; i++)
    {
        if (unicode_str[i] == '\x0A')
        {
            break;
        }
        type = get_align_type(unicode_str[i]);
        if (type != align_type_unknown)
        {
            return type;
        }
    }
    return align_type_right;
}

#ifdef X86_TEST
#include <stdio.h>
uint16_t const test_src_0[] = {0x627, 0x644, 0x633, 0x644, 0x627, 0x645, 0x20, 0x639, 0x644, 0x64a, 0x643, 0x645, 0};
uint16_t const test_dest_0[] = {0xfe8d, 0xfedf, 0xfeb4, 0xfefc, 0xfee1, 0x20, 0xfecb, 0xfee0, 0xfef4, 0xfedc, 0xfee2, 0};
uint16_t const test_src_1[] = {0x627, 0x644, 0x633, 0x64e, 0x644, 0x64e, 0x627, 0x652, 0x645, 0x64c, 0x20, 0x639, 0x64e, 0x644, 0x64e, 0x64a, 0x652, 0x643, 0x64f, 0x645, 0x652, 0};
uint16_t const test_dest_1[] = {0xfe8d, 0xfedf, 0xfeb4, 0xfefc, 0xfee1, 0x20, 0xfecb, 0xfee0, 0xfef4, 0xfedc, 0xfee2, 0};
uint16_t const test_src_2[] = {0x627, 0x644, 0x644, 0x63a, 0x629, 0x20,  0x627, 0x644, 0x639, 0x631, 0x628, 0x64a, 0x629, 0x20, 0x647,
                               0x64a, 0x20,  0x623, 0x643, 0x62b, 0x631, 0x20,  0x627, 0x644, 0x644, 0x63a, 0x627, 0x62a, 0};
uint16_t const test_dest_2[] = {0xfe8d, 0xfedf, 0xfee0, 0xfed0, 0xfe94, 0x20,   0xfe8d, 0xfedf, 0xfecc, 0xfeae, 0xfe91, 0xfef4, 0xfe94, 0x20, 0xfeeb,
                                0xfef2, 0x20,   0xfe83, 0xfedb, 0xfe9c, 0xfeae, 0x20,   0xfe8d, 0xfedf, 0xfee0, 0xfed0, 0xfe8e, 0xfe95, 0};
uint16_t const test_src_3[] = {0x62a, 0x62d, 0x62f, 0x62b, 0x627, 0x64b, 0x20, 0x648, 0x646, 0x637, 0x642, 0x627, 0x64b, 0x20, 0x636, 0x645, 0x646, 0x20, 0x645, 0x62c, 0x645, 0x648, 0x639, 0x629, 0};
uint16_t const test_dest_3[] = {0xfe97, 0xfea4, 0xfeaa, 0xfe9b, 0xfe8e, 0x20,   0xfeed, 0xfee7, 0xfec4, 0xfed8, 0xfe8e, 0x20,
                                0xfebf, 0xfee4, 0xfee6, 0x20,   0xfee3, 0xfea0, 0xfee4, 0xfeee, 0xfecb, 0xfe94, 0};
uint16_t const test_src_4[] = {0x627, 0x644, 0x644, 0x63a, 0x627, 0x62a, 0x20, 0x627, 0x644, 0x633, 0x627, 0x645, 0x64a, 0x629, 0};
uint16_t const test_dest_4[] = {0xfe8d, 0xfedf, 0xfee0, 0xfed0, 0xfe8e, 0xfe95, 0x20, 0xfe8d, 0xfedf, 0xfeb4, 0xfe8e, 0xfee3, 0xfef4, 0xfe94, 0};
uint16_t const test_src_5[] = {0x627, 0x644, 0x639, 0x631, 0x628, 0x64a, 0x629, 0x20, 0x644, 0x63a, 0x629, 0x20, 0x631, 0x633, 0x645, 0x64a, 0x629, 0x20, 0x641, 0x64a, 0};
uint16_t const test_dest_5[] = {0xfe8d, 0xfedf, 0xfecc, 0xfeae, 0xfe91, 0xfef4, 0xfe94, 0x20, 0xfedf, 0xfed0, 0xfe94, 0x20, 0xfead, 0xfeb3, 0xfee4, 0xfef4, 0xfe94, 0x20, 0xfed3, 0xfef2, 0};
uint16_t const test_src_6[] = {0x643, 0x644, 0x20, 0x62f, 0x648, 0x644, 0x20, 0x627, 0x644, 0x648, 0x637, 0x646, 0x20, 0x627, 0x644, 0x639, 0x631, 0x628, 0x64a, 0};
uint16_t const test_dest_6[] = {0xfedb, 0xfede, 0x20, 0xfea9, 0xfeed, 0xfedd, 0x20, 0xfe8d, 0xfedf, 0xfeee, 0xfec3, 0xfee6, 0x20, 0xfe8d, 0xfedf, 0xfecc, 0xfeae, 0xfe91, 0xfef2, 0};
uint16_t const test_src_7[] = {0x625, 0x636, 0x627, 0x641, 0x629, 0x20, 0x625, 0x644, 0x649, 0x20, 0x643, 0x648, 0x646, 0x647, 0x627, 0x20, 0x644, 0x63a, 0x629, 0};
uint16_t const test_dest_7[] = {0xfe87, 0xfebf, 0xfe8e, 0xfed3, 0xfe94, 0x20, 0xfe87, 0xfedf, 0xfef0, 0x20, 0xfedb, 0xfeee, 0xfee7, 0xfeec, 0xfe8e, 0x20, 0xfedf, 0xfed0, 0xfe94, 0};
uint16_t const test_src_8[] = {0x631, 0x633, 0x645, 0x64a, 0x629, 0x20, 0x641, 0x64a, 0x20, 0x62a, 0x634, 0x627, 0x62f, 0x20, 0x648, 0x625, 0x631, 0x64a, 0x62a, 0x631, 0x64a, 0x627, 0};
uint16_t const test_dest_8[] = {0xfead, 0xfeb3, 0xfee4, 0xfef4, 0xfe94, 0x20,   0xfed3, 0xfef2, 0x20,   0xfe97, 0xfeb8, 0xfe8e,
                                0xfea9, 0x20,   0xfeed, 0xfe87, 0xfead, 0xfef3, 0xfe98, 0xfeae, 0xfef3, 0xfe8e, 0};
uint16_t const test_src_9[] = {0x648, 0x625, 0x633, 0x631, 0x627, 0x626, 0x64a, 0x644, 0x2e,  0x20,  0x648, 0x647, 0x64a,
                               0x20,  0x625, 0x62d, 0x62f, 0x649, 0x20,  0x627, 0x644, 0x644, 0x63a, 0x627, 0x62a, 0};
uint16_t const test_dest_9[] = {0xfeed, 0xfe87, 0xfeb3, 0xfeae, 0xfe8d, 0xfe8b, 0xfef4, 0xfede, 0x2e,   0x20,   0xfeed, 0xfeeb, 0xfef2,
                                0x20,   0xfe87, 0xfea3, 0xfeaa, 0xfeef, 0x20,   0xfe8d, 0xfedf, 0xfee0, 0xfed0, 0xfe8e, 0xfe95, 0};
uint16_t const test_src_10[] = {0x627, 0x644, 0x631, 0x633, 0x645, 0x64a, 0x629, 0x20, 0x627, 0x644, 0x633, 0x62a, 0x20, 0x641, 0x64a, 0x20, 0x645, 0x646, 0x638, 0x645, 0x629, 0};
uint16_t const test_dest_10[] = {0xfe8d, 0xfedf, 0xfeae, 0xfeb3, 0xfee4, 0xfef4, 0xfe94, 0x20, 0xfe8d, 0xfedf, 0xfeb4, 0xfe96, 0x20, 0xfed3, 0xfef2, 0x20, 0xfee3, 0xfee8, 0xfec8, 0xfee4, 0xfe94, 0};
uint16_t const test_src_11[] = {0x627, 0x644, 0x623, 0x645, 0x645, 0x20, 0x627, 0x644, 0x645, 0x62a, 0x62d, 0x62f, 0x629, 0x60c, 0x20, 0x648, 0x64a, 0x64f, 0x62d, 0x62a, 0x641, 0x644, 0};
uint16_t const test_dest_11[] = {0xfe8d, 0xfef7, 0xfee3, 0xfee2, 0x20, 0xfe8d, 0xfedf, 0xfee4, 0xfe98, 0xfea4, 0xfeaa, 0xfe93, 0x60c, 0x20, 0xfeed, 0xfef3, 0xfea4, 0xfe98, 0xfed4, 0xfede, 0};
uint16_t const test_src_12[] = {0x628, 0x627, 0x644, 0x64a, 0x648, 0x645, 0x20,  0x627, 0x644, 0x639, 0x627, 0x644, 0x645, 0x64a,
                                0x20,  0x644, 0x644, 0x63a, 0x629, 0x20,  0x627, 0x644, 0x639, 0x631, 0x628, 0x64a, 0x629, 0};
uint16_t const test_dest_12[] = {0xfe91, 0xfe8e, 0xfedf, 0xfef4, 0xfeee, 0xfee1, 0x20,   0xfe8d, 0xfedf, 0xfecc, 0xfe8e, 0xfedf, 0xfee4, 0xfef2,
                                 0x20,   0xfedf, 0xfee0, 0xfed0, 0xfe94, 0x20,   0xfe8d, 0xfedf, 0xfecc, 0xfeae, 0xfe91, 0xfef4, 0xfe94, 0};
uint16_t const test_src_13[] = {0x641, 0x64a, 0x20,  0x31,  0x38,  0x20, 0x62f, 0x64a, 0x633, 0x645, 0x628, 0x631, 0x20,
                                0x643, 0x630, 0x643, 0x631, 0x649, 0x20, 0x627, 0x639, 0x62a, 0x645, 0x627, 0x62f, 0};
uint16_t const test_dest_13[] = {0xfed3, 0xfef2, 0x20,   0x31,   0x38,   0x20, 0xfea9, 0xfef3, 0xfeb4, 0xfee4, 0xfe92, 0xfeae, 0x20,
                                 0xfedb, 0xfeac, 0xfedb, 0xfeae, 0xfeef, 0x20, 0xfe8d, 0xfecb, 0xfe98, 0xfee4, 0xfe8e, 0xfea9, 0};
uint16_t const test_src_14[] = {0x627, 0x644, 0x639, 0x631, 0x628, 0x64a, 0x629, 0x20,  0x628, 0x64a, 0x646, 0x20,  0x644,
                                0x63a, 0x627, 0x62a, 0x20,  0x627, 0x644, 0x639, 0x645, 0x644, 0x20,  0x641, 0x64a, 0};
uint16_t const test_dest_14[] = {0xfe8d, 0xfedf, 0xfecc, 0xfeae, 0xfe91, 0xfef4, 0xfe94, 0x20,   0xfe91, 0xfef4, 0xfee6, 0x20,   0xfedf,
                                 0xfed0, 0xfe8e, 0xfe95, 0x20,   0xfe8d, 0xfedf, 0xfecc, 0xfee4, 0xfede, 0x20,   0xfed3, 0xfef2, 0};
uint16_t const test_src_15[] = {0x627, 0x644, 0x623, 0x645, 0x645, 0x20, 0x627, 0x644, 0x645, 0x62a, 0x62d, 0x62f, 0x629, 0x2e, 0};
uint16_t const test_dest_15[] = {0xfe8d, 0xfef7, 0xfee3, 0xfee2, 0x20, 0xfe8d, 0xfedf, 0xfee4, 0xfe98, 0xfea4, 0xfeaa, 0xfe93, 0x2e, 0};

typedef struct __test_case_t
{
    uint16_t const *src;
    uint16_t const *dest;
} test_case_t;
test_case_t const test_case[] = {
    {test_src_0, test_dest_0},   {test_src_1, test_dest_1},   {test_src_2, test_dest_2},   {test_src_3, test_dest_3},   {test_src_4, test_dest_4},   {test_src_5, test_dest_5},
    {test_src_6, test_dest_6},   {test_src_7, test_dest_7},   {test_src_8, test_dest_8},   {test_src_9, test_dest_9},   {test_src_10, test_dest_10}, {test_src_11, test_dest_11},
    {test_src_12, test_dest_12}, {test_src_13, test_dest_13}, {test_src_14, test_dest_14}, {test_src_15, test_dest_15},
};
int main()
{
    uint16_t test_temp[100] = {0};
    int result = 0;
    for (int i = 0; i < sizeof(test_case) / sizeof(test_case[0]); i++)
    {
        memset(test_temp, 0, sizeof(test_temp));
        memcpy(test_temp, test_case[i].src, wcslen(test_case[i].src) * 2);
        printf("src: ");
        for (int j = 0; j < wcslen(test_temp); j++)
        {
            printf("0x%02x ", test_temp[j]);
        }
        printf("\n");
        reshaper(test_temp);
        result = wcscmp(test_temp, test_case[i].dest);
        if (result != 0)
        {
            printf("reshaper fail!\n");
            for (int j = 0; j < wcslen(test_temp); j++)
            {
                printf("0x%02x ", test_temp[j]);
            }
            printf("\n");
            for (int j = 0; j < wcslen(test_case[i].dest); j++)
            {
                printf("0x%02x ", test_case[i].dest[j]);
            }
            printf("\n");
        }
        else
        {
            printf("reshaper success!\n");
        }
    }
    // uint16_t const *test_string = u"123";
    // uint16_t test_array[100] = {0x627,'1','2','3','a' };
    ////wcscpy(test_array, test_string);
    // for (uint32_t i = 0; i < wcslen(test_array); i++)
    //{
    //    printf("0x%02x ", test_array[i]);
    //}
    // printf("\r\n");
    // align_type_t align_type = arabic_reshaper(test_array);
    // printf("align_type[%d]: \n", align_type);
    // for (uint32_t i = 0; i < wcslen(test_array); i++)
    //{
    //    printf("0x%02x ", test_array[i]);
    //}
}
#endif
